package rexsee.service;

import rexsee.core.browser.Browser;
import rexsee.core.browser.clazz.JavascriptInterface;
import rexsee.core.lang.RexseeLanguage;
import rexsee.core.utilities.Utilities;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Handler;

public class RexseePushHttpListener implements JavascriptInterface {

	public static final String INTERFACE_NAME = "PushHttpListener";
	@Override
	public String getInterfaceName() {
		return (httpBrowser == null) ? null : httpBrowser.application.resources.prefix + INTERFACE_NAME;
	}
	@Override
	public JavascriptInterface getInheritInterface(Browser childBrowser) {
		return this;
	}
	@Override
	public JavascriptInterface getNewInterface(Browser childBrowser) {
		return new RexseePushHttpListener(childBrowser);
	}

	private static final String EVENT_ONPUSHREFRESHFINISHED = "onPushRefreshFinished";
	private static final int HTTP_DEFAULT_DURATION = 5; //minutes
	private static final int HTTP_DEFAULT_TIMEOUT = 10; //seconds
	private static final String PUSH_HTTP_DEFAULT_ENCODING = "UTF-8";

	private final Context httpContext;
	private final Browser httpBrowser;
	private final Handler httpHandler;
	private Runnable httpRunnable = null;

	public RexseePushHttpListener(Context context) {
		httpContext = context;
		httpHandler = new Handler();
		httpBrowser = null;
		RexseePush.initDatabase(context);
	}
	public RexseePushHttpListener(Browser browser) {
		httpContext = browser.getContext();
		httpHandler = new Handler();
		httpBrowser = browser;
		browser.eventList.add(EVENT_ONPUSHREFRESHFINISHED);
		RexseePush.initDatabase(httpContext);
	}

	public void register() {
		httpRunnable = new Runnable() {
			@Override
			public void run() {
				try {
					refresh();
					httpHandler.postDelayed(httpRunnable, getDuration() * 1000 * 60);
				} catch (Exception e) {
				}
			}
		};
		httpHandler.postDelayed(httpRunnable, 1000);
	}

	private HttpItem[] getItems() {
		SQLiteDatabase db = httpContext.openOrCreateDatabase(RexseePush.DATABASE_PUSH, Context.MODE_PRIVATE, null);
		Cursor cursor = db.rawQuery("SELECT * from " + RexseePush.TABLE_PUSH_HTTP + ";", null);
		if (cursor == null) return null;
		int count = cursor.getCount();
		if (count == 0) return null;
		HttpItem[] rtn = new HttpItem[count];
		for (int i = 0; i < count; i++) {
			cursor.moveToPosition(i);
			rtn[i] = new HttpItem(cursor.getString(0), cursor.getString(1), cursor.getString(2), cursor.getString(3));
		}
		try {
			cursor.close();
		} catch (Exception e) {
		}
		db.close();
		return rtn;
	}

	//JavaScript Interface
	public boolean contains(String url) {
		HttpItem[] tmp = getItems();
		if (tmp == null) return false;
		for (int i = 0; i < tmp.length; i++) {
			if (tmp[i].url.equals(url)) return true;
		}
		return false;
	}
	public void add(String url, String userId, String userPassword) { //For compatibility
		add(url, userId, userPassword, PUSH_HTTP_DEFAULT_ENCODING);
	}
	public void add(String url, String userId, String userPassword, String encoding) {
		url = httpBrowser.urlListeners.getAbsoluteUrl(url);
		String scheme = Uri.parse(url).getScheme();
		if (!scheme.equals("http") && !scheme.equals("https")) {
			httpBrowser.exception(getInterfaceName(), "Wrong Scheme!");
			return;
		}
		if (!httpBrowser.domainWhiteList.isValidUrl(url)) {
			httpBrowser.exception(getInterfaceName(), "Url not allowed.");
			return;
		}
		try {
			SQLiteDatabase db = httpContext.openOrCreateDatabase(RexseePush.DATABASE_PUSH, Context.MODE_PRIVATE, null);
			db.execSQL("DELETE FROM " + RexseePush.TABLE_PUSH_HTTP + " WHERE url='" + url + "';");
			db.execSQL("INSERT INTO " + RexseePush.TABLE_PUSH_HTTP + " VALUES ('" + url + "','" + userId + "','" + userPassword + "','" + encoding + "');");
			db.close();
		} catch (Exception e) {
		}
	}
	public String get(String url) {
		url = httpBrowser.urlListeners.getAbsoluteUrl(url);
		HttpItem[] tmp = getItems();
		if (tmp == null) return "";
		for (int i = 0; i < tmp.length; i++) {
			if (tmp[i].url.equals(url)) return tmp[i].toString();
		}
		return "";
	}
	public String get() {
		HttpItem[] tmp = getItems();
		if (tmp == null) return "";
		String rtn = "";
		for (int i = 0; i < tmp.length; i++) {
			rtn += (i == 0) ? "\"" + tmp[i].url + "\"" : ",\"" + tmp[i].url + "\"";
		}
		return "[" + rtn + "]";
	}
	public void remove(String url) {
		url = httpBrowser.urlListeners.getAbsoluteUrl(url);
		try {
			SQLiteDatabase db = httpContext.openOrCreateDatabase(RexseePush.DATABASE_PUSH, Context.MODE_PRIVATE, null);
			db.execSQL("DELETE FROM " + RexseePush.TABLE_PUSH_HTTP + " WHERE url='" + url + "';");
			db.close();
		} catch (Exception e) {
		}
	}

	public void setDurationAndTimeout(int durationMinutes, int timeoutSeconds) {
		try {
			SQLiteDatabase db = httpContext.openOrCreateDatabase(RexseePush.DATABASE_PUSH, Context.MODE_PRIVATE, null);
			db.execSQL("DELETE FROM " + RexseePush.TABLE_PUSH_HTTP_ARGUMENTS + ";");
			db.execSQL("INSERT INTO " + RexseePush.TABLE_PUSH_HTTP_ARGUMENTS + " VALUES (" + durationMinutes + "," + timeoutSeconds + ");");
			db.close();
		} catch (Exception e) {
		}
	}
	public int getDuration() {
		try {
			SQLiteDatabase db = httpContext.openOrCreateDatabase(RexseePush.DATABASE_PUSH, Context.MODE_PRIVATE, null);
			Cursor cursor = db.rawQuery("SELECT duration from " + RexseePush.TABLE_PUSH_HTTP_ARGUMENTS + ";", null);
			int rtn;
			if (cursor == null || cursor.getCount() == 0) {
				rtn = HTTP_DEFAULT_DURATION;
			} else {
				cursor.moveToFirst();
				rtn = cursor.getInt(0);
			}
			try {
				cursor.close();
			} catch (Exception e) {
			}
			db.close();
			return rtn;
		} catch (Exception e) {
			return HTTP_DEFAULT_DURATION;
		}
	}
	public int getTimeout() {
		try {
			SQLiteDatabase db = httpContext.openOrCreateDatabase(RexseePush.DATABASE_PUSH, Context.MODE_PRIVATE, null);
			Cursor cursor = db.rawQuery("SELECT timeout from " + RexseePush.TABLE_PUSH_HTTP_ARGUMENTS + ";", null);
			int rtn;
			if (cursor == null || cursor.getCount() == 0) {
				rtn = HTTP_DEFAULT_TIMEOUT;
			} else {
				cursor.moveToFirst();
				rtn = cursor.getInt(0);
			}
			try {
				cursor.close();
			} catch (Exception e) {
			}
			db.close();
			return rtn;
		} catch (Exception e) {
			return HTTP_DEFAULT_TIMEOUT;
		}
	}

	public int getLastMessageId(String url) {
		if (httpBrowser != null) url = httpBrowser.urlListeners.getAbsoluteUrl(url);
		try {
			SQLiteDatabase db = httpContext.openOrCreateDatabase(RexseePush.DATABASE_PUSH, Context.MODE_PRIVATE, null);
			Cursor cursor = db.rawQuery("SELECT id from " + RexseePush.TABLE_PUSH + " WHERE type='" + RexseePush.PUSH_TYPE_HTTP + "' and address='" + url + "' ORDER BY date DESC LIMIT 1;", null);
			int rtn;
			if (cursor == null || cursor.getCount() == 0) {
				rtn = -1;
			} else {
				cursor.moveToFirst();
				rtn = cursor.getInt(0);
			}
			try {
				cursor.close();
			} catch (Exception e) {
			}
			db.close();
			return rtn;
		} catch (Exception e) {
			return -1;
		}
	}
	public void refresh() {
		refresh(true, true);
	}
	public void refresh(final boolean progress, final boolean finishAlert) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				HttpItem[] items = getItems();
				if (items == null) {
					if (httpBrowser != null) httpBrowser.exception(getInterfaceName(), "No available push url.");
					return;
				}
				if (httpBrowser != null && progress) httpBrowser.progressDialog.show(RexseeLanguage.PROGRESS_ONGOING);
				for (int i = 0; i < items.length; i++) {
					String url = items[i].url + "?id=" + items[i].userId + "&password=" + items[i].userPassword + "&last=" + getLastMessageId(items[i].url);
					String data = Utilities.getContent(httpContext, url, null, items[i].encoding);
					if (data != null) RexseePush.add(httpContext, RexseePush.PUSH_TYPE_HTTP, System.currentTimeMillis(), items[i].url, data);
				}
				if (httpBrowser != null) {
					if (progress) httpBrowser.progressDialog.hide();
					if (finishAlert) httpBrowser.application.alert(RexseeLanguage.PROGRESS_REFRESH_FINISH);
					httpBrowser.eventList.run(EVENT_ONPUSHREFRESHFINISHED);
				}
			}
		}).start();
	}

}
